#ifndef _CONTAINER_RUN_HPP_
#define _CONTAINER_RUN_HPP_

#ifdef __cplusplus

#include <dlcom/unknown.h>
#include <dlcom/loadcom.hpp>

class CContainer
{
public:
    CContainer() { }
    virtual ~CContainer()
    {
        m_pIMainRun.dispose();
        m_loader.UnloadCom();
    }

    HRESULT LoadContainer(const SafePStringPtr* path)
    {
        HRESULT hr = S_OK;

        rc_error(path != NULL, E_FAIL);
        rc_error(path->len != 0, E_FAIL);
        rc_error(path->ptr != NULL, E_FAIL);

        m_loader.UnloadCom();
        m_pIMainRun.dispose();

        basic_tchar szContainerName[DYNAMIC_NAME_LEN + 1] = {0x00};
        get_dynamicname(_T("container"), szContainerName, DYNAMIC_NAME_LEN);

        m_strContainerPath.clear();
        m_strContainerPath.append(path->ptr);
        m_strContainerPath.append(path_slash);
        m_strContainerPath.append(szContainerName);

        hr = m_loader.LoadCom(m_strContainerPath.c_str());
        rc_error(hr == S_OK, E_FAIL);

        hr = m_loader.CreateInstance(CLSID_CMainRun, INULL, INULL, IID_IMainRun, (void**)&m_pIMainRun);
        rc_error(((hr == S_OK) && (m_pIMainRun != INULL)), E_FAIL);

        return hr;
    }

    HRESULT CreateContainer(REFCLSID rid, const SafePStringPtr* path, const SafeStringPtr* code)
    {
        HRESULT hr = S_OK;
        rc_error(m_pIMainRun != NULL, E_FAIL);
        _lComPtr<IObjectRun> pIObjectRun;
        hr = m_pIMainRun->CreateObject(rid, (IBase**)&pIObjectRun, path, code);
        rc_error(hr == S_OK, E_FAIL);

        pIObjectRun.dispose();

        return S_OK;
    }

    HRESULT ExitContainer(REFCLSID rid, UINT exit)
    {
        HRESULT hr = S_OK;
        _lComPtr<IObjectRun> pIObjectRun;
        m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, E_FAIL);
        rc_error(hr == S_OK, E_FAIL);

        return pIObjectRun->Exit(exit);
    }

    HRESULT RegisterContainer(REFCLSID rid, UINT type, UINT version)
    {
        HRESULT hr = S_OK;
        _lComPtr<IObjectRun> pIObjectRun;
        hr = m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, E_FAIL);
        rc_error(hr == S_OK, E_FAIL);

        return pIObjectRun->Registers(type, version);
    }

    HRESULT InitContainer(REFCLSID rid, _pid_t pid, basic_tchar* argv[], int argc)
    {
        HRESULT hr = S_OK;
        _lComPtr<IObjectRun> pIObjectRun;
        hr = m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, E_FAIL);
        rc_error(hr == S_OK, E_FAIL);

        hr = pIObjectRun->Load();
        rc_error(hr == S_OK, E_FAIL);

        return pIObjectRun->Init(pid, argv, argc);
    }

    HRESULT StartContainer(REFCLSID rid, UINT type)
    {
        HRESULT hr = S_OK;
        _lComPtr<IObjectRun> pIObjectRun;
        m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, E_FAIL);
        rc_error(hr == S_OK, E_FAIL);

        return pIObjectRun->Start(type);
    }

    HRESULT StopContainer(REFCLSID rid, UINT type, UINT exit)
    {
        HRESULT hr = S_OK;
        _lComPtr<IObjectRun> pIObjectRun;
        m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, E_FAIL);
        rc_error(hr == S_OK, E_FAIL);

        return pIObjectRun->Stop(type, exit);
    }

    HRESULT RegisterComponent(REFCLSID rid, REFCLSID clsid, LPCSTR progid, IBase* pBase, ULONG id, LPCSTR plugin, UINT type)
    {
        HRESULT hr = S_OK;
        rc_error(progid != NULL, E_FAIL);
        rc_error(pBase != NULL, E_FAIL);

        _lComPtr<IObjectRun> pIObjectRun;
        m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, E_FAIL);
        rc_error(hr == S_OK, E_FAIL);

        return pIObjectRun->AddObject(clsid, progid, pBase, id, plugin, type);
    }

    HRESULT RunContainer(REFCLSID rid, UINT type)
    {
        HRESULT hr = S_OK;
        _lComPtr<IObjectRun> pIObjectRun;
        m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, E_FAIL);
        rc_error(hr == S_OK, E_FAIL);

        UINT code = OBJECT_RUN_RET_SUCCESS;

        // logi("m_pIObjectRun->Start==>%u", type);
        hr = pIObjectRun->Start(type);
        rc_error(hr == S_OK, E_FAIL);

        code = pIObjectRun->GetExitCode();

        logi("m_pIObjectRun->Stop==>%u", code);
        return pIObjectRun->Stop(type, code);
    }

    HRESULT UnInitContainer(REFCLSID rid)
    {
        HRESULT hr = S_OK;
        _lComPtr<IObjectRun> pIObjectRun;
        m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, E_FAIL);
        rc_error(hr == S_OK, E_FAIL);

        return pIObjectRun->Uninit();
    }

    UINT GetContainerExitCode(REFCLSID rid)
    {
        HRESULT hr = S_OK;
        _lComPtr<IObjectRun> pIObjectRun;
        m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, OBJECT_RUN_RET_ERROR);
        rc_error(hr == S_OK, E_FAIL);

        return pIObjectRun->GetExitCode();
    }

    ULONG GetStartIndex(REFCLSID rid, ULONG index)
    {
        HRESULT hr = S_OK;
        _lComPtr<IObjectRun> pIObjectRun;
        m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, OBJECT_RUN_RET_ERROR);
        rc_error(hr == S_OK, E_FAIL);

        return pIObjectRun->GetRunIndex(index);
    }

    ULONG GetCompentCount(REFCLSID rid)
    {
        HRESULT hr = S_OK;
        _lComPtr<IObjectRun> pIObjectRun;
        m_pIMainRun->GetObjectRun(rid, (IBase**)&pIObjectRun);
        rc_error(pIObjectRun != NULL, OBJECT_RUN_RET_ERROR);
        rc_error(hr == S_OK, E_FAIL);

        return pIObjectRun->GetRunPluginsCount();
    }

private:
    CComLoader m_loader;
    path_string m_strContainerPath;
    _lComPtr<IMainRun> m_pIMainRun;
};

#endif

#endif
